package com.boot.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boot.annotation.RateLimit;
import com.boot.constants.StatusConstants;
import com.boot.dto.*;
import com.boot.entity.*;
import com.boot.exception.BusinessException;
import com.boot.mapper.QuestionAssignmentMapper;
import com.boot.service.*;
import com.boot.utils.SecurityUtils;
import com.boot.utils.UserContext;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/questions")
@Slf4j
public class QuestionController {
    private static final Logger logger = LoggerFactory.getLogger("OPERATION_LOG");

    @Resource
    private IQuestionService questionService;

    @Resource
    private IQuestionAssignmentService questionAssignmentService;

    @Resource
    private QuestionAssignmentMapper assignmentMapper;

    @Resource
    private IAttachmentService attachmentService;

    @Resource
    private ICommentService commentService;

    @Resource
    private IUserService userService;

    /**
     * 发布新问题
     */
    @RateLimit(limit = 5, windowSec = 60)
    @PostMapping
    public Result<Long> publishQuestion(@Valid @RequestBody PublishQuestionDTO dto) {
        try {
            SecurityUtils.requireCurrentUserId();

            // 检查是否能发布
            if (!questionService.canUserPublish()) {
                return Result.fail("已存在未解决的问题，不能发布新的问题");
            }

            Long questionId = questionService.publishQuestion(dto);
            return Result.success(questionId);
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }

    @RateLimit(limit = 50, windowSec = 60)
    @GetMapping("/my/published")
    public Result<Page<QuestionDTO>> getMyPublishedQuestions(@RequestParam(defaultValue = "1") int current, @RequestParam(defaultValue = "10") int size) {
        try {
            Long userId = SecurityUtils.requireCurrentUserId();

            Page<Question> page = new Page<>(current, size);
            Page<Question> questionPage = questionService.getMyPublishedQuestions(page, userId);

            List<QuestionDTO> records = questionPage.getRecords().stream()
                    .map(this::convertToDTO)
                    .collect(Collectors.toList());

            Page<QuestionDTO> dtoPage = copyPage(questionPage, records);

            return Result.success(dtoPage);
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }

    @RateLimit(limit = 50, windowSec = 60)
    @GetMapping("/my/handled")
    public Result<Page<QuestionDTO>> getMyHandledQuestions(@RequestParam(defaultValue = "1") int current, @RequestParam(defaultValue = "10") int size) {
        try {
            Long expertId = SecurityUtils.requireCurrentUserId();

            Page<Question> page = new Page<>(current, size);
            Page<Question> questionPage = questionService.getHandledQuestionsByExpertId(page, expertId);

            List<QuestionDTO> records = questionPage.getRecords().stream()
                    .map(this::convertToDTO)
                    .collect(Collectors.toList());

            Page<QuestionDTO> dtoPage = copyPage(questionPage, records);

            return Result.success(dtoPage);
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }

    // 辅助方法：复制分页信息到 DTO 分页对象
    private <T> Page<T> copyPage(Page<?> source, List<T> records) {
        Page<T> target = new Page<>();
        target.setCurrent(source.getCurrent());
        target.setSize(source.getSize());
        target.setTotal(source.getTotal());
        target.setRecords(records);
        return target;
    }

    // 转换实体为 DTO（避免暴露敏感字段）
    private QuestionDTO convertToDTO(Question question) {
        QuestionDTO dto = new QuestionDTO();
        dto.setId(question.getId());
        dto.setTitle(question.getTitle());
        dto.setType(question.getType());
        dto.setStatus(question.getStatus());
        dto.setCreatedAt(question.getCreatedAt());
        dto.setResolvedAt(question.getResolvedAt());
        dto.setResolvedAt(question.getResolvedAt());

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper
                .eq("id", question.getUserId())
                .select("username");
        User user = userService.getOne(wrapper);
        if (user != null) {
            dto.setRequester(user.getUsername());
        }

        return dto;
    }

    /**
     * 修改问题（仅限 pending_review 状态）
     */
    @PostMapping("/{id}/update")
    @RateLimit(limit = 5, windowSec = 60)
    public Result<String> updateQuestion(@Valid @RequestBody PublishQuestionDTO dto, @PathVariable Long id) {
        try {
            SecurityUtils.requireCurrentUserId();

            // ✅ 传入 id
            questionService.updateQuestion(dto, id);
            return Result.success("问题信息更新成功");
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }

    /**
     * 删除问题（仅限 pending_review 状态）
     */
    @RateLimit(limit = 50, windowSec = 60)
    @DeleteMapping("/{id}")
    @Transactional(rollbackFor = Exception.class)
    public Result<String> deleteQuestion(@PathVariable Long id) {
        try {
            Long userId = SecurityUtils.requireCurrentUserId();

            Question question = questionService.getById(id);
            if (question == null) {
                return Result.fail("问题不存在");
            }

            if (!question.getUserId().equals(userId)) {
                return Result.fail("无权限删除他人问题");
            }

            // 删除关联的 assignment 记录
            QueryWrapper<QuestionAssignment> wrapper = new QueryWrapper<>();
            wrapper.eq("question_id", id);
            assignmentMapper.delete(wrapper);

            // 删除主问题
            boolean removed = questionService.removeById(id);
            if (removed) {
                attachmentService.deleteAttachmentsForQuestion(id);
                commentService.deleteCommentsForQuestion(id);
                return Result.success("问题已删除");
            } else {
                return Result.fail("删除失败，请重试");
            }
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }

    /**
     * 专家接收任务
     */
    @RateLimit(limit = 50, windowSec = 60)
    @PatchMapping("/{id}/accept")
    @Transactional(rollbackFor = Exception.class)
    public Result<String> acceptTask(@PathVariable Long id) {
        try {
            Long expertId = SecurityUtils.requireCurrentUserId();

            // 查找该专家对该问题的分配记录
            QueryWrapper<QuestionAssignment> wrapper = new QueryWrapper<>();
            wrapper.eq("question_id", id).eq("expert_id", expertId);
            QuestionAssignment assignment = questionAssignmentService.getOne(wrapper);

            if (assignment == null) {
                return Result.fail("未被指定为此问题的处理人");
            }

            if (StatusConstants.AssignmentStatus.ACCEPTED.equals(assignment.getAccepted())) {
                return Result.fail("您已接受此任务");
            }
            if (StatusConstants.AssignmentStatus.REJECTED.equals(assignment.getAccepted())) {
                return Result.fail("您已拒绝此任务，不可再次接受");
            }

            // 检查问题是否存在且状态正确
            Question question = questionService.getById(id);
            if (question == null) {
                return Result.fail("问题不存在");
            }

            if (!StatusConstants.QuestionStatus.WAITING.equals(question.getStatus()) && !StatusConstants.QuestionStatus.PENDING_REVIEW.equals(question.getStatus())) {
                return Result.fail("任务不可接受（可能已被他人接单或已解决）");
            }

            // 设置为已接受
            assignment.setAccepted(StatusConstants.AssignmentStatus.ACCEPTED);
            assignment.setRespondedAt(LocalDateTime.now());
            questionAssignmentService.updateById(assignment);

            // 更新问题状态为 in_progress
            question.setStatus(StatusConstants.QuestionStatus.IN_PROGRESS);
            questionService.updateById(question);

            // 关闭其他专家的响应机会（设置为 REJECTED）
            List<QuestionAssignment> others = assignmentMapper.selectList(
                    new QueryWrapper<QuestionAssignment>()
                            .eq("question_id", id)
                            .ne("expert_id", expertId)
                            .isNull("accepted") // 仅更新尚未响应的
            );

            for (QuestionAssignment other : others) {
                other.setAccepted(StatusConstants.AssignmentStatus.REJECTED);
                other.setRespondedAt(LocalDateTime.now());
            }
            if (!others.isEmpty()) {
                questionAssignmentService.updateBatchById(others);
            }

            return Result.success("任务已接受，开始处理");
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }

    /**
     * 专家拒绝任务
     */
    @RateLimit(limit = 50, windowSec = 60)
    @PatchMapping("/{id}/reject")
    public Result<String> rejectTask(@PathVariable Long id) {
        try {
            Long expertId = SecurityUtils.requireCurrentUserId();

            QueryWrapper<QuestionAssignment> wrapper = new QueryWrapper<>();
            wrapper.eq("question_id", id).eq("expert_id", expertId);
            QuestionAssignment assignment = questionAssignmentService.getOne(wrapper);

            if (assignment == null) {
                return Result.fail("未被指定为此问题的处理人");
            }

            if (assignment.getAccepted() != null) {
                return Result.fail("您已处理过该任务（接受或拒绝），不可重复操作");
            }

            // 拒绝并记录时间
            assignment.setAccepted(StatusConstants.AssignmentStatus.REJECTED);
            assignment.setRespondedAt(LocalDateTime.now());
            questionAssignmentService.updateById(assignment);

            // 👇 新增：检查是否所有人都已拒绝
            List<QuestionAssignment> allAssignments = questionAssignmentService.list(
                    new QueryWrapper<QuestionAssignment>().eq("question_id", id)
            );

            boolean hasAccepted = allAssignments.stream()
                    .anyMatch(a -> StatusConstants.AssignmentStatus.ACCEPTED.equals(a.getAccepted()));
            boolean allResponded = allAssignments.stream()
                    .allMatch(a -> a.getAccepted() != null);

            Question question = questionService.getById(id);

            if (!hasAccepted && allResponded) {
                // 所有人都拒绝了，无人接手！

                // 更新问题状态为“等待管理员处理”
                question.setStatus(StatusConstants.QuestionStatus.AWAITING_ADMIN);
                question.setReviewNotes("所有专家均已拒绝接单，请管理员介入分配或重新指派专家。");
                questionService.updateById(question);

                // 可选：发送通知给管理员（邮件、站内信等）
                logger.warn("问题[ID={}]因所有专家拒绝，已转交管理员处理", id);
            }

            return Result.success("已拒绝该任务");
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }

    @GetMapping("/{id}")
    @RateLimit(limit = 50, windowSec = 60)
    public Result<QuestionDetailDTO> getQuestionDetail(@PathVariable Long id) {
        try {
            Long userId = SecurityUtils.requireCurrentUserId();

            Question question = questionService.getById(id);
            if (question == null) {
                return Result.fail("问题不存在");
            }

            // 权限检查：必须是提问者本人或处理专家
            if (!question.getUserId().equals(userId)) {
                // 检查是否为被分配且已接受的专家
                QueryWrapper<QuestionAssignment> wrapper = new QueryWrapper<>();
                wrapper.eq("question_id", id)
                        .eq("expert_id", userId)
                        .and(w -> w
                                .isNull("accepted")           // 待响应
                                .or()
                                .eq("accepted", StatusConstants.AssignmentStatus.ACCEPTED)   // 或已接受
                        );
                boolean isAssignedExpert = questionAssignmentService.count(wrapper) > 0;
                if (!isAssignedExpert) {
                    return Result.fail("无权限查看该问题详情");
                }
            }

            QuestionDetailDTO dto = new QuestionDetailDTO();
            dto.setId(question.getId());
            dto.setTitle(question.getTitle());
            dto.setType(question.getType());
            dto.setDescription(question.getDescription());
            dto.setExpected(question.getExpected());
            dto.setStatus(question.getStatus());
            dto.setCreatedAt(question.getCreatedAt());
            dto.setResolvedAt(question.getResolvedAt());

            // 查询附件
            List<Attachment> attachments = attachmentService.listAttachmentsByQuestionId(id);
            List<AttachmentDTO> attachmentDTOS = attachments.stream().map(att -> {
                AttachmentDTO adto = new AttachmentDTO();
                adto.setId(att.getId());
                adto.setName(att.getFileName());
                adto.setSizeKb(att.getSizeKb());
                adto.setMimeType(att.getMimeType());
                adto.setCreatedAt(att.getCreatedAt());
                return adto;
            }).collect(Collectors.toList());

            dto.setAttachments(attachmentDTOS);

            // =================== 新增：查询待处理专家列表 ===================
            // 获取所有该问题下的专家 assignment 记录
            List<QuestionAssignment> pendingAssignments = assignmentMapper.selectList(
                    new QueryWrapper<QuestionAssignment>()
                            .eq("question_id", id)
            );

            if (!pendingAssignments.isEmpty()) {
                // 提取 expertId 列表
                List<Long> expertIds = pendingAssignments.stream()
                        .map(QuestionAssignment::getExpertId)
                        .collect(Collectors.toList());

                // 查询这些专家的基本信息（只选 id 和 username）
                List<User> experts = userService.list(
                        new QueryWrapper<User>()
                                .in("id", expertIds)
                                .select("id", "username")  // 关键：避免查出 password
                );

                // 转换为 DTO
                List<UserSummaryDTO> pendingExperts = experts.stream().map(u -> {
                    UserSummaryDTO summary = new UserSummaryDTO();
                    summary.setId(u.getId());
                    summary.setUsername(u.getUsername());
                    return summary;
                }).collect(Collectors.toList());

                dto.setPendingExperts(pendingExperts);
            } else {
                dto.setPendingExperts(Collections.emptyList());
            }

            return Result.success(dto);
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }

    @RateLimit(limit = 5, windowSec = 60)
    @PatchMapping("/{id}/resolve")
    public Result<String> resolveQuestion(@PathVariable Long id) {
        try {
            boolean success = questionService.markAsResolved(id);
            if (success) {
                return Result.success("问题已成功标记为已解决");
            } else {
                return Result.fail("标记失败，请重试");
            }
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }
}
